#include "JudgeDredd.h"
#include "GomokuBitmask.h"
#include "GameException.h"

JudgeDredd::JudgeDredd(void)
{
}


JudgeDredd::~JudgeDredd(void)
{
}

void	JudgeDredd::putPieceOnMap(GameInfo& game, coord_t& coord)
{
	this->twinTriple(game, coord);
	game.putPieceOnMap(coord);
	game.incScore(takeAPiece(game, coord));
	this->lookAlignement(game, coord);
	game.endRoundOfPlayer();
}



void	JudgeDredd::twinTriple(GameInfo& game, coord_t& coord)
{
	
}

char	JudgeDredd::takeAPiece(GameInfo& game, coord_t& coord)
{
	char count = 0;
	if (coord.y > 2 && 
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y - 1][coord.x]) == true &&
		CHECKMASK(game.getMap()[coord.y - 1][coord.x], TAKENMASKH) == true)
		count++, game.takeOffPieceOnBoard(coord.y - 1, coord.x, NORTH);

	if (coord.y + 3 < LENGTHBOARD && 
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y + 1][coord.x]) == true &&
		CHECKMASK(game.getMap()[coord.y + 1][coord.x], TAKENMASKH) == true)
		count++, game.takeOffPieceOnBoard(coord.y + 1, coord.x, SOUTH);
	
	if (coord.x > 2 && 
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y][coord.x - 1]) == true &&
		CHECKMASK(game.getMap()[coord.y][coord.x - 1], TAKENMASKV) == true)
		count++, game.takeOffPieceOnBoard(coord.y, coord.x - 1, WEST);

	if (coord.x + 3 < LENGTHBOARD && 
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y][coord.x + 1]) == true &&
		CHECKMASK(game.getMap()[coord.y][coord.x + 1], TAKENMASKV) == true)
		count++, game.takeOffPieceOnBoard(coord.y, coord.x + 1, EAST);

	if (coord.x > 2 && coord.y > 2 &&
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y - 1 ][coord.x - 1]) &&
		CHECKMASK(game.getMap()[coord.y - 1][coord.x - 1], TAKENMASKDNS) == true)
		count++, game.takeOffPieceOnBoard(coord.y - 1, coord.x - 1, NORTHWEST);

	if (coord.x + 3 < LENGTHBOARD && coord.y + 3 < LENGTHBOARD &&
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y + 1 ][coord.x + 1]) &&
		CHECKMASK(game.getMap()[coord.y + 1][coord.x + 1], TAKENMASKDNS) == true)
		count++, game.takeOffPieceOnBoard(coord.y + 1, coord.x + 1, SOUTHEAST);

	if (coord.x > 2 && coord.y + 3 < LENGTHBOARD &&
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y + 1 ][coord.x - 1]) &&
		CHECKMASK(game.getMap()[coord.y + 1][coord.x - 1], TAKENMASKDNS) == true)
		count++, game.takeOffPieceOnBoard(coord.y + 1, coord.x - 1, SOUTHWEST);

	if (coord.x + 3 < LENGTHBOARD && coord.y > 2 &&
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y - 1 ][coord.x + 1]) &&
		CHECKMASK(game.getMap()[coord.y - 1][coord.x + 1], TAKENMASKDNS) == true)
		count++, game.takeOffPieceOnBoard(coord.y - 1, coord.x + 1, NORTHEAST);
	return count;
}

void JudgeDredd::lookAlignement(GameInfo& game, coord_t& coord)
{
	int		count;
	int		stop = 0;
	int**	tmp = game.getMap();
	int		n[4];

	n[0] = 0;
	n[1] = 0;
	n[2] = 0;
	n[3] = 0;

	if (CHECKMASK(tmp[coord.y][coord.x], CPH) != true)
		stop |= (1 | 2);
	if (CHECKMASK(tmp[coord.y][coord.x], CPV) != true)
		stop |= (4 | 8);
	if (CHECKMASK(tmp[coord.y][coord.x], CPDNS) != true)
		stop |= (16 | 32);
	if (CHECKMASK(tmp[coord.y][coord.x], CPDSN) != true)
		stop |= (64 | 128);

	for (count = 0; count < LENGTHBOARD && stop < 255; count++)
	{
		if (CHECKMASK(stop, 1) != true)
		{
			if (coord.y - count > 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y - count][coord.x]) != true)
				stop |= checkTaken(tmp[coord.y - count][coord.x], NORTH);
			else
				stop |= 1;
			if (CHECKMASK(stop, 1) != true)
				n[0]++;
		}
		if (CHECKMASK(stop, 2) != true)
		{
			if (coord.y + count < LENGTHBOARD &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y + count][coord.x]) != true)
				stop |= checkTaken(tmp[coord.y + count][coord.x], SOUTH);
			else
				stop |= 2;
			if (CHECKMASK(stop, 2) != true)
				n[0]++;
		}
		if (CHECKMASK(stop, 4) != true)
		{
			if (coord.x - count > 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y][coord.x - count]) != true)
				stop |= checkTaken(tmp[coord.y][coord.x - count], WEST);
			else
				stop |= 4;
			if (CHECKMASK(stop, 4) != true)
				n[1]++;
		}
		if (CHECKMASK(stop, 8) != true)
		{
			if (coord.x + count < LENGTHBOARD &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y][coord.x + count]) != true)
				stop |= checkTaken(tmp[coord.y][coord.x + count], EAST);
			else
				stop |= 8;
			if (CHECKMASK(stop, 8) != true)
				n[1]++;
		}
		if (CHECKMASK(stop, 16) != true)
		{
			if (coord.x - count > 0 && coord.y - count > 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y - count][coord.x - count]) != true)
				stop |= checkTaken(tmp[coord.y - count][coord.x - count], NORTHWEST);
			else
				stop |= 16;
			if (CHECKMASK(stop, 16) != true)
				n[2]++;
		}
		if (CHECKMASK(stop, 32) != true)
		{
			if (coord.x + count < LENGTHBOARD && coord.y + count < LENGTHBOARD &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y + count][coord.x + count]) != true)
				stop |= checkTaken(tmp[coord.y + count][coord.x + count], SOUTHEAST);
			else
				stop |= 32;
			if (CHECKMASK(stop, 32) != true)
				n[2]++;
		}
		if (CHECKMASK(stop, 64) != true)
		{
			if (coord.x + count > LENGTHBOARD && coord.y - count > 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y - count][coord.x + count]) != true)
				stop |= checkTaken(tmp[coord.y - count][coord.x + count], NORTHEAST);
			else
				stop |= 64;
			if (CHECKMASK(stop, 64) != true)
				n[3]++;
		}
		if (CHECKMASK(stop, 128) != true)
		{
			if (coord.x - count < 0 && coord.y + count < LENGTHBOARD &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y + count][coord.x - count]) != true)
				stop |= checkTaken(tmp[coord.y + count][coord.x - count], SOUTHWEST);
			else
				stop |= 128;
			if (CHECKMASK(stop, 128) != true)
				n[3]++;
		}
		if (n[0] >= 5 || n[1] >= 5 || n[2] >= 5 || n[3] >= 5)
		{
                        //GameExceptionWinByAlignement& exc = GameExceptionWinByAlignement();
                        GameExceptionWinByAlignement exc = GameExceptionWinByAlignement();
                        throw exc;
                }
	}
}

int	JudgeDredd::checkTaken(int point, Way dir)
{
	int ret = 0;
	int tmp = point & TOTALV;

	if (tmp == (UPH | DPH | TLH) || 
		tmp == (UPH | DPH | TRH))
		return makeAnswer(dir);
	if (tmp == (UPV | DPV | TLV) || 
		tmp == (UPV | DPV | TRV))
		return makeAnswer(dir);
	if (tmp == (UPDNS | DPDNS | TLDNS) || 
		tmp == (UPDNS | DPDNS | TRDNS))
		return makeAnswer(dir);
	if (tmp == (UPDSN | DPDSN | TLDSN) || 
		tmp == (UPDSN | DPDSN | TRDSN))
		return makeAnswer(dir);
	return 0;
}

int JudgeDredd::makeAnswer(Way dir)
{
	if (dir == NORTH)
		return 1;
	if (dir == SOUTH)
		return 2;
	if (dir == WEST)
		return 4;
	if (dir == EAST)
		return 8;
	if (dir == NORTHWEST)
		return 16;
	if (dir == SOUTHEAST)
		return 32;
	if (dir == NORTHEAST)
		return 64;
	if (dir == SOUTHWEST)
		return 128;
	return 0;
}
